package com.otomotion.research.ants.databank;

import com.otomotion.research.ants.entities.Ant;
import com.otomotion.research.ants.information.Coordinate;
import com.otomotion.research.ants.information.InfoLeaf;
import com.otomotion.research.ants.information.InfoNode;
import com.otomotion.research.ants.util.LOGGER;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;
import java.util.Vector;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;

/**
 * @author joel
 */
public class UberRepository {
	private DirtRepository dirtRepository;

	private AntRepository antRepository;

	private int x;

	private int y;

	private int z;

	public UberRepository(int x, int y, int z) {
		LOGGER.logln("Creating UberReposistory dimensioned at: "
				+ new Coordinate(x, y, z).toString() + " ... ");
		LOGGER.log("DONE");
		this.x = x;
		this.y = y;
		this.z = z;
		this.dirtRepository = new DirtRepository(x, y, z);
		this.antRepository = new AntRepository();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#getIdleAnts()
	 */
	public Collection<Ant> getIdleAnts() {
		return antRepository.getIdleAnts();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#getLocationOf(com.otomotion.research.ants.entities.Ant)
	 */
	public Coordinate getLocationOf(Ant ant) {
		return this.antRepository.getLocationOfAnt(ant);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#getInformationForCoordinates(java.util.Collection)
	 */
	public InfoNode getInformationForCoordinates(Collection coordinates) {
		InfoNode info = new InfoNode();
		Iterator i = coordinates.iterator();
		while (i.hasNext()) {
			Coordinate c = (Coordinate) i.next();
			InfoNode node = this.getInformationForCoordinate(c);
			info.addInformation(node);

		}
		return info;
	}

	private InfoNode getInformationForCoordinate(Coordinate c) {
		InfoNode node = new InfoNode();
		if (dirtRepository.isDirt(c.getX(), c.getY(), c.getZ())) {
			node.addInformation(new InfoLeaf(c, "dirt"));
		}
		if (antRepository.hasAnt(c)) {
			node.addInformation(new InfoLeaf(c, "ant"));
		}
		return node;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#hasAnt(com.otomotion.research.ants.information.Coordinate)
	 */
	public boolean hasAnt(Coordinate location) {
		return this.antRepository.hasAnt(location);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#hasDirt(com.otomotion.research.ants.information.Coordinate)
	 */
	public boolean hasDirt(Coordinate location) {
		return dirtRepository.isDirt(location.getX(), location.getY(), location
				.getZ());
	}

	public boolean isDirtMovable(Coordinate location) {
		return (!(location.getX() == 0 || location.getX() == x - 1
				|| location.getY() == 0 || location.getY() == y - 1
				|| location.getZ() == 0 || location.getZ() == z - 1));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#clearDirt(com.otomotion.research.ants.information.Coordinate)
	 */
	public void clearDirt(Coordinate c) {
		this.dirtRepository.clearDirt(c.getX(), c.getY(), c.getZ());

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#putDirt(com.otomotion.research.ants.information.Coordinate)
	 */
	public void putDirt(Coordinate c) {
		this.dirtRepository.setDirt(c.getX(), c.getY(), c.getZ());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#populate(int)
	 */
	public void populate(int n) {
		int a = 0;
		for (int i = 0; i < n; i++) {
			Random r = new Random();
			Coordinate here = new Coordinate(r.nextInt(x), r.nextInt(y), z / 2);
			if (!dirtRepository.isDirt(here.getX(), here.getY(), here.getZ()))
				if (antRepository.addAnt(here))
					a++;
		}
		LOGGER.log(a + " ants generated");

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.otomotion.research.ants.databank.RepositoryInterface#moveAntTo(com.otomotion.research.ants.entities.Ant,
	 *      com.otomotion.research.ants.information.Coordinate)
	 */
	public void moveAntTo(Ant ant, Coordinate coordinate) {
		antRepository.moveAnt(ant, coordinate);
	}

	public Document getInformation(Integer id, Integer r) {
		Ant a = this.antRepository.getAntById(id);
		if (a != null) {
			Coordinate l = a.getLocation();
			return this.getInformation(l.add(new Coordinate(-r, -r, -r)), l
					.add(new Coordinate(r, r, r)));
		} else
			return getInformation();
	}

	public Document getInformation() {
		return this.getInformation(new Coordinate(0, 0, 0), new Coordinate(x,
				y, z));
	}

	public Document getInformation(Coordinate c1, Coordinate c2) {
		System.out.println("getting information...");
		Document data = new Document();
		Element root = new Element("data");
		data.setRootElement(root);

		int startX = c1.getX();
		int endX = c2.getX();
		if (startX > endX) {
			int tmp = endX;
			endX = startX;
			startX = tmp;
		}
		int startY = c1.getY();
		int endY = c2.getY();
		if (startY > endY) {
			int tmp = endY;
			endY = startY;
			startY = tmp;
		}
		int startZ = c1.getZ();
		int endZ = c2.getZ();
		if (startZ > endZ) {
			int tmp = endZ;
			endZ = startZ;
			startZ = tmp;
		}

		for (int i = startX; i <= endX; i++) {
			for (int j = startY; j <= endY; j++) {
				for (int k = startZ; k <= endZ; k++) {
					Coordinate here = new Coordinate(i, j, k);
					Element e = new Element("coordinate");
					e.setAttribute("x", String.valueOf(i));
					e.setAttribute("y", String.valueOf(j));
					e.setAttribute("z", String.valueOf(k));
					boolean add = false;
					if (this.hasDirt(here)) {
						add = true;
						e.addContent(new Element("dirt"));
					}
					if (this.hasAnt(here)) {
						add = true;
						e.addContent(new Element("ant"));
					}
					if (add)
						root.addContent(e);
				}
			}
		}
		root.setAttribute("test", "test");
		// XMLOutputter out = new XMLOutputter();

		System.out.println(new XMLOutputter().outputString(root));

		return data;
	}

}
